package websocket;

import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import javax.sound.sampled.*;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;

public class WebSocketAudioClient extends WebSocketClient {

    // 设置音频格式和输入流
    private static final AudioFormat AUDIO_FORMAT = new AudioFormat(16000, 16, 1, true, false); // 16kHz 单声道 16位 PCM

    private volatile static int i = 0;

    public WebSocketAudioClient(URI serverUri) {
        super(serverUri);
    }

    @Override
    public void onOpen(ServerHandshake serverHandshake) {
        System.out.println("WebSocket Connected!");
        Thread thread = new Thread(this::startRecording);
        thread.setDaemon(false);
        thread.start();
    }

    @Override
    public void onMessage(ByteBuffer bytes) {
        System.out.println("Received from server: " + Arrays.toString(bytes.array()));
    }

    @Override
    public void onMessage(String message) {
        System.out.println("Received from server: " + message);
    }

    @Override
    public void onClose(int code, String reason, boolean remote) {
        System.out.println("WebSocket Closed!");
    }

    @Override
    public void onError(Exception ex) {
        System.out.println("onError -> "+ex.getMessage());
        ex.printStackTrace();
    }

    // 开始录音
    private void startRecording() {
        try {
            DataLine.Info info = new DataLine.Info(TargetDataLine.class, AUDIO_FORMAT);
            TargetDataLine targetDataLine = (TargetDataLine) AudioSystem.getLine(info);
            targetDataLine.open(AUDIO_FORMAT);
            targetDataLine.start();

            System.out.println("Recording started...");

            send("{\n" +
                    "\"mode\": \"2pass\",\n" +
                    "\"chunk_size\": [5, 10, 5],\n" +
                    "\"encoder_chunk_look_back\": 4,\n" +
                    "\"decoder_chunk_look_back\": 1,\n" +
                    "\"chunk_interval\": 10, \n" +
                    "\"wav_name\": \"default\",\n" +
                    "\"is_speaking\": true\n" +
                    "}");

            // 测试 send error
//            onError(new Exception("test error"));

            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[1920];

            while (i == 0) {
                int bytesRead = targetDataLine.read(buffer, 0, buffer.length);
                if (bytesRead > 0) {
                    byteArrayOutputStream.write(buffer, 0, bytesRead);
                    byte[] pcmData = byteArrayOutputStream.toByteArray();
                    send(pcmData); // 通过 WebSocket 发送数据
                    byteArrayOutputStream.reset(); // 重置输出流
                }
            }
            targetDataLine.stop();
            targetDataLine.close();
            System.out.println("Recording closed...");

            send("{\n" +
                    "\"mode\": \"2pass\",\n" +
                    "\"chunk_size\": [5, 10, 5],\n" +
                    "\"encoder_chunk_look_back\": 4,\n" +
                    "\"decoder_chunk_look_back\": 1,\n" +
                    "\"chunk_interval\": 10, \n" +
                    "\"wav_name\": \"default\",\n" +
                    "\"is_speaking\": false\n" +
                    "}");
            close();
        } catch (LineUnavailableException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            try {
                URI serverUri = new URI("ws://127.0.0.1:9010/websocket/1/2222");
//                URI serverUri = new URI("ws://127.0.0.1:9010/websocket/1/"+System.currentTimeMillis());
                WebSocketAudioClient client = new WebSocketAudioClient(serverUri);
                client.connectBlocking();
//                client.connect();
            } catch (InterruptedException | URISyntaxException e) {
                e.printStackTrace();
            }
        });
        thread.setDaemon(false);
        thread.start();

        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            try {
                WebSocketAudioClient.i = 1;
                TimeUnit.SECONDS.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }));
    }
}
